﻿/*+========================================================
File:		QuadTree.cpp
Sumary:	Hiện thực hóa các phương thức của lớp CTreeObject và
CQNode
========================================================+*/
#include "QuadTree.h"
#include "GameObject.h"
#include <algorithm>    // std::unique, std::distance

struct IDGreater{
	bool operator()(CGameObject* lx, CGameObject* rx) const {
		return lx->GetId() < rx->GetId();
	}
};

CQNode::CQNode()
{
	m_pLT = NULL;
	m_pRT = NULL;
	m_pLB = NULL;
	m_pRB = NULL;
}

CQNode::CQNode(int id, float x1, float y1, float x2, float y2)
{
	m_pLT = NULL;
	m_pRT = NULL;
	m_pLB = NULL;
	m_pRB = NULL;

	m_nId = id;
	m_x1 = x1;
	m_x2 = x2;
	m_y1 = y1;
	m_y2 = y2;
}

CQNode::CQNode(int id, float x1, float y1, float x2, float y2, vector<int> idList, map<int, CGameObject*>& gameObjects)
{
	m_pLT = NULL;
	m_pRT = NULL;
	m_pLB = NULL;
	m_pRB = NULL;

	m_nId = id;
	m_x1 = x1;
	m_x2 = x2;
	m_y1 = y1;
	m_y2 = y2;

	for (int i = 0; i < idList.size(); i++)
	{
		int tmpId = idList[i];
		map<int, CGameObject*>::iterator iResult;
		iResult = gameObjects.find(tmpId);

		if (iResult != gameObjects.end())
			m_aGameObject.push_back(iResult->second);
	}
}

CQNode::~CQNode()
{
	if (m_pLT)
		delete m_pLT;
	if (m_pRT)
		delete m_pRT;
	if (m_pLB)
		delete m_pLB;
	if (m_pRB)
		delete m_pRB;
}

void CQNode::AddNodeLT(CQNode* lt)
{
	m_pLT = lt;
}

void CQNode::AddNodeRT(CQNode* rt)
{
	m_pRT = rt;
}

void CQNode::AddNodeLB(CQNode* lb)
{
	m_pLB = lb;
}

void CQNode::AddNodeRB(CQNode* rb)
{
	m_pRB = rb;
}

void CQNode::GetObjectsInVP(Box vpBox, vector<CGameObject*>* listGameObject)
{
	//Box nodeBox = { m_x1, m_y1, abs(m_x2 - m_x1), abs(m_y2 - m_y1), 0.0f, 0.0f };

	if (m_nId == 27)
	{
		int i = 5;
	}

	Box nodeBox = { m_x1, m_y1, abs(m_x2 - m_x1), abs(m_y2 - m_y1), 0.0f, 0.0f };

	if (nodeBox.IsIntersect(vpBox))
	{
		if (!this->m_pLT && !this->m_pLB && !this->m_pRT && !this->m_pRB)
		{
			listGameObject->insert(
				listGameObject->end(),
				m_aGameObject.begin(),
				m_aGameObject.end()
				);


			// Sắp xếp lại list để các phần tử giống gần nhau.
			std::sort(listGameObject->begin(), listGameObject->end(), IDGreater());

			// Xóa các phần tử giống, giữ lại phần tử giống đầu tiên.
			listGameObject->erase(std::unique(listGameObject->begin(), listGameObject->end()), listGameObject->end());
			
		}
		else
		{
			this->m_pLT->GetObjectsInVP(vpBox, listGameObject);
			this->m_pRT->GetObjectsInVP(vpBox, listGameObject);
			this->m_pLB->GetObjectsInVP(vpBox, listGameObject);
			this->m_pRB->GetObjectsInVP(vpBox, listGameObject);
		}
	}
	else
	{
		return;
	}
}